"use strict";
var Utf8 = require("./utf8");

function indexof(code) {
    if (65 <= code && code <= 90) {//A-Z
        return code - 65;
    } else if (97 <= code && code <= 122) {//a-z
        return code - 71;
    } else if (48 <= code && code <= 57) {//0-9
        return code + 4;
    } else if (43 == code) {//+
        return 62;
    } else if (47 == code) {// /
        return 63;
    } else if (!code||61 == code) {// =  !code 是怕最后的=被去除了
        return 64;
    }else {
        return -1;
    }
}

function code(index) {
    if (0 <= index && index <= 25) {//0-25
        return index + 65;
    } else if (26 <= index && index <= 51) {//26-51
        return index + 71;
    } else if (52 <= index && index <= 61) {//52-61
        return index - 4;
    } else if (62 == index) {//62
        return 43;
    } else if (63 == index) {// 63
        return 47;
    } else if (64 == index) {// 64
        return 61;
    }
}

/**
 *
 * @param input {string,Array<number>}
 * @returns {Array<number>}
 */
function encode(input) {
    var output = [];
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var i = 0;
    if (typeof input === "string") {
        input = Utf8.toBytes(input);
    }
    while (i < input.length) {
        chr1 = input[i++];
        chr2 = input[i++];
        chr3 = input[i++];
        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;
        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }
        output.push(code(enc1));
        output.push(code(enc2));
        output.push(code(enc3));
        output.push(code(enc4));
    }
    return output;
}
function encodeStr(input) {
    return Utf8.toStr(encode(input));
}
/**
 *
 * @param input {string,Array<number>}
 * @returns {Array<number>}
 */
function decode(input) {
    var output = [];
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;
    var isStr;
    var isNumberArray;
    if (isStr = typeof input === "string") {
        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
        while (input.length%4!=0){
            input+='=';
        }
    } else/* if (Array.isArray(input) && typeof input[0] === "number")*/ {//因为 Uint8Array 所以这里去掉
        isNumberArray = true;
        //todo 这里这样有问题 先注释掉
        // while (input.length%4!=0){
        //     input[input.length] = '='.charCodeAt(0);
        // }
    }
    //todo 数组情况没去除 非法字符
    while (i < input.length) {
        if (isStr) {
            enc1 = indexof(input.charCodeAt(i++));
            enc2 = indexof(input.charCodeAt(i++));
            enc3 = indexof(input.charCodeAt(i++));
            enc4 = indexof(input.charCodeAt(i++));
        } else if (isNumberArray) {
            enc1 = indexof(input[i++]);
            if(-1==enc1 && i%77==0 ) {//todo 其他情况没处理
                if (i==input.length){//最后一个是附加的换行符
                    break
                }
                enc1=indexof(input[i++]);
            }
            enc2 = indexof(input[i++]);
            enc3 = indexof(input[i++]);
            enc4 = indexof(input[i++]);
        }
        chr1 = (enc1 << 2) | (enc2 >> 4);
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
        chr3 = ((enc3 & 3) << 6) | enc4;
        output.push(chr1);
        if (enc3 != 64) {
            output.push(chr2);
        }
        if (enc4 != 64) {
            output.push(chr3);
        }
    }
    return output;
}
function decodeStr(input) {
    return Utf8.toStr(decode(input));
}
module.exports = {encode,encodeStr,decode,decodeStr};